package com.lanyou.cook.web;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Tuple;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.lanyou.cook.common.Constants;
import com.lanyou.cook.entity.domain.Field;
import com.lanyou.cook.entity.domain.FieldSystem;
import com.lanyou.cook.entity.domain.userManagement.User;
import com.lanyou.cook.repository.FieldRepository;
import com.lanyou.cook.repository.FieldSystemRepository;
import com.lanyou.cook.service.security.UserSessionService;
import com.lanyou.cook.util.DateUtil;
import com.lanyou.cook.web.param.FieldParam;

/**
 * 领域管理相关业务控制层
 * @author 曾族根
 *
 */
@RestController
@RequestMapping(Constants.BASE_URL_API + "/fields")
public class FieldController {
	@PersistenceContext
	private EntityManager entityManager;
	@Autowired
	private FieldRepository fieldRepository;
	@Autowired
	private FieldSystemRepository fieldSystemRepository;

	/**
	 * 查询特定条件下的领域集合
	 * @param param	类型:FieldParam 待查询的领域参数实体
	 * @param pageable 类型:Pageable 待查询的分页参数实体
	 * @return
	 */
	@RequestMapping("/search/findByExample")
	@RequiresPermissions(value={"fieldManagement:view","fieldManagement:maintain"},logical=Logical.OR)
	public Page<Field> findByExample(FieldParam param, Pageable pageable){
		
		Specification<Field> spec = new Specification<Field>() {
			@Override
			public Predicate toPredicate(Root<Field> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicatesList = new ArrayList<>();
				if(StringUtils.isNotBlank(param.getName())){
					predicatesList.add(cb.like(root.get("name"), '%' + param.getName() + '%'));
				}
				
				// 纠正错误的时间参数
				DynaBean fixedDates = DateUtil.fixBeginTimeAndEndTime(param.getBeginOfCreateTime(), param.getEndOfCreateTime());
				Date fixedBeginTime = (Date)fixedDates.get("begin");
				Date fixedEndTime = (Date)fixedDates.get("end");
				
				Path<Date> pathDate = root.get("createTime");
				predicatesList.add(cb.or(cb.isNull(pathDate), cb.between(pathDate, fixedBeginTime, fixedEndTime)));
				query.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
				return null;
			}
		};
		return fieldRepository.findAll(spec, pageable);
	}
	
	/**
	 * 获取所有的领域
	 * @return 类型:List<Field> 返回一个领域集合
	 */
	@RequestMapping("/search/findAllFields")
	public String findAllFields(){
		/*return fieldRepository.findAll();*/
		CriteriaBuilder cb = entityManager.getCriteriaBuilder();
		CriteriaQuery<Tuple> cq = cb.createTupleQuery().distinct(true);
		
		// 构建FROM和JOIN部分
		Root<Field> rootField = cq.from(Field.class);/*
		Join<Field, FieldSystem> joinFieldSystem = rootField.join("fieldSystems");
		Join<FieldSystem, User> joinUser = joinFieldSystem.join("users");*/
		
		// 构建WHERE部分
		/*cq.where(cb.equal(joinUser.get("userCode"), userCode));*/
		
		// 构建SELECT部分
		cq.multiselect(rootField.get("id").alias("id"), rootField.get("name").alias("name"));
		
		/*cq.orderBy(cb.asc(rootField.get("name")));*/

		// 执行查询
		TypedQuery<Tuple> q = entityManager.createQuery(cq);
		List<Tuple> queryResult = q.getResultList();
		
		JsonArray jsonDatas = new JsonArray();
		Collator chineseCmp = Collator.getInstance(java.util.Locale.CHINA);
		queryResult.stream()
			.sorted(Comparator.comparing(t -> t.get("name", String.class), chineseCmp))
			.forEach( tuple -> {
				String id = tuple.get("id", String.class);
				String name = tuple.get("name", String.class);
				
				JsonObject jo = new JsonObject();
				jo.addProperty("id", id);
				jo.addProperty("name", name);
				jsonDatas.add(jo);
		});
		
		
		JsonObject jsonResult = new JsonObject();
		jsonResult.add("content", jsonDatas);
		return jsonResult.toString();
	}
	
	
	/**
	 * 获取当前登录用户所管理的领域
	 * @return 类型:String 返回当前登录用户所管理的所有领域
	 */
	@RequestMapping(value = "/search/findAllOfCurrentUserCanManage", produces = "application/json")
	public String findAllOfCurrentUserCanManage(){
		String userCode = UserSessionService.getCurrentAuthenticatedUserCode();
		if (userCode == null)
			throw new UnauthenticatedException();
		
		CriteriaBuilder cb = entityManager.getCriteriaBuilder();
		CriteriaQuery<Tuple> cq = cb.createTupleQuery().distinct(true);
		
		// 构建FROM和JOIN部分
		Root<Field> rootField = cq.from(Field.class);
		Join<Field, FieldSystem> joinFieldSystem = rootField.join("fieldSystems");
		Join<FieldSystem, User> joinUser = joinFieldSystem.join("users");
		
		// 构建WHERE部分
		cq.where(cb.equal(joinUser.get("userCode"), userCode));
		
		// 构建SELECT部分
		cq.multiselect(rootField.get("id").alias("id"), rootField.get("name").alias("name"));

		//cq.orderBy(cb.asc(rootField.get("name")));
		
		// 执行查询
		TypedQuery<Tuple> q = entityManager.createQuery(cq);
		List<Tuple> queryResult = q.getResultList();
		
		JsonArray jsonDatas = new JsonArray();
		Collator chineseCmp = Collator.getInstance(java.util.Locale.CHINA);
		queryResult.stream()
			.sorted(Comparator.comparing(t -> t.get("name", String.class), chineseCmp))
			.forEach( tuple -> {
				String id = tuple.get("id", String.class);
				String name = tuple.get("name", String.class);
				
				JsonObject jo = new JsonObject();
				jo.addProperty("id", id);
				jo.addProperty("name", name);
				jsonDatas.add(jo);
		});
		
		
		JsonObject jsonResult = new JsonObject();
		jsonResult.add("content", jsonDatas);
		return jsonResult.toString();
	}
	
	/**
	 * 判断待删除的领域下面是否存在系统
	 * @param id 类型:String 待删除领域的ID
	 * @return 类型:String 判断后返回的结果(存在返回false,不存在返回true)
	 */
	@RequestMapping(value="/search/checkIsCanDelete", produces="application/json")
	public String checkIsCanDelete(String id){
		long count = fieldSystemRepository.countByField_Id(id);
		
		if(count > 0){
			JsonObject result = new JsonObject();
			result.addProperty("isCanDelete", false);
			result.addProperty("reason", "该领域下存在领域系统，不能删除");
			return result.toString();
		} else {
			JsonObject result = new JsonObject();
			result.addProperty("isCanDelete", true);
			return result.toString();
		}
	}
	@RequestMapping(value = "/search/checkIsCanSave", produces = "application/json")
	public String checkIsCanSave(String name,String originalId) {
		Field field = fieldRepository.findByName(name);
			if (field != null) {
			if (!StringUtils.equals(field.getId(), originalId)) {
				JsonObject result = new JsonObject();
				result.addProperty("isCanSave", false);
				result.addProperty("errorCode", "DUPLICATE");
				return result.toString();
			}
		}

		JsonObject result = new JsonObject();
		result.addProperty("isCanSave", true);
		return result.toString();
	}
	
	@RequestMapping(value = "/findOne/{id}")
	@RequiresPermissions(value={"fieldManagement:view","fieldManagement:maintain"},logical=Logical.OR)
	public Field findOne(@PathVariable String id) {
		return fieldRepository.findOne(id);
	}
}
